/*
 * $Author: isan.wong@gmail.com $
 * $Date: 2011-07-29 01:03:06 +0000 (Fri, 29 Jul 2011) $
 * $Rev: 13 $
 * $URL: http://capitalbio-smd.googlecode.com/svn/src/com/capitalbio/smd/base/Result.java $
 */

package com.capitalbio.smd.base;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.biojava.bio.symbol.SymbolList;

/**
 * 分析结果
 * 
 * @author Wang Lei
 */
public class Result {
	
	protected Log log = LogFactory.getLog(this.getClass());

	private SymbolList seq0;
	private SymbolList seq1;
	private SymbolList seq2;

	private int offset;
	private List<Variation> variations;
	private List<Variation> optimizedVariations;

	private Properties properties;

	/**
	 * 用于分析的原始测序序列 (可能是编辑过的)
	 */
	private SymbolList symbolList;

	/**
	 * 用于记录除去 gap 后的有效索引
	 */
	private int[] validIndex;

	/**
	 * 标准基因
	 */
	private StdGene stdGene;

	/**
	 * create new result using the specified properties
	 * 
	 * @param properties
	 * @param stdGene
	 * @param symbolList
	 * @param seq0
	 * @param seq1
	 * @param seq2
	 */
	public Result(Properties properties, StdGene stdGene,
			SymbolList symbolList, SymbolList seq0, SymbolList seq1,
			SymbolList seq2, int offset) {
		this.properties = properties;
		this.stdGene = stdGene;
		this.offset = offset;

		this.seq0 = seq0;
		this.seq1 = seq1;
		this.seq2 = seq2;

		setSymbolList(symbolList);
	}

	public int getOffset() {
		return offset;
	}

	public void setOffset(int offset) {
		this.offset = offset;
	}

	/**
	 * get variations
	 * 
	 * @return variations list
	 */
	public List<Variation> getVariations() {
		if (variations == null) {

			variations = Variation.searchVariations(
					VariationLocation.VariationLocationType.C, offset, stdGene,
					seq0, seq1, seq2);
		}
		return variations;
	}

	/**
	 * get optimized variations
	 * @return optimized variations list
	 */
	public List<Variation> getOptimizedVariations() {
		if (optimizedVariations == null) {
			optimizedVariations = new ArrayList<Variation>();
			for (Variation variation : getVariations()) {
				if (optimizedVariations.size() != 0) {
					Variation lastVariation = optimizedVariations
							.get(optimizedVariations.size() - 1);
					log.debug(lastVariation);
					if (lastVariation.canJoin(variation)) {
						Variation newVariation = lastVariation.join(variation);
						optimizedVariations.set(optimizedVariations.size() - 1, newVariation);
					}
					else {
						Variation newVariation = new Variation(variation.getType(),
								variation.getLocation(), variation.getSource(),
								variation.getTarget());
						optimizedVariations.add(newVariation);
					}
				} else {
					Variation newVariation = new Variation(variation.getType(),
							variation.getLocation(), variation.getSource(),
							variation.getTarget());
					optimizedVariations.add(newVariation);
				}
			}
		}
		return optimizedVariations;
	}

	/**
	 * 比对结果中标准序列的子序列
	 * 
	 * @return 比对结果中标准序列的子序列
	 */
	public SymbolList getSeq0() {
		return seq0;
	}

	/**
	 * 比对结果中标准序列的子序列
	 * 
	 * @param seq0
	 *            比对结果中标准序列的子序列
	 */
	public void setSeq0(SymbolList seq0) {
		this.seq0 = seq0;
	}

	/**
	 * 比对结果中测序序列的子序列
	 * 
	 * @return 比对结果中测序序列的子序列
	 */
	public SymbolList getSeq1() {
		return seq1;
	}

	/**
	 * 比对结果中测序序列的子序列
	 * 
	 * @param seq1
	 *            比对结果中测序序列的子序列
	 */
	public void setSeq1(SymbolList seq1) {
		this.seq1 = seq1;
	}

	/**
	 * 比对结果中测序序列单一链的子序列
	 * 
	 * @return 比对结果中测序序列单一链的子序列
	 */
	public SymbolList getSeq2() {
		return seq2;
	}

	/**
	 * 比对结果中测序序列单一链的子序列
	 * 
	 * @param seq2
	 *            比对结果中测序序列单一链的子序列
	 */
	public void setSeq2(SymbolList seq2) {
		this.seq2 = seq2;
	}

	public SymbolList getSymbolList() {
		return symbolList;
	}

	/**
	 * 返回除去 gap 后的有效索引
	 * 
	 * @param i
	 * @return 除去 gap 后的有效索引
	 */
	public int getValidIndex(int i) {
		if (i < 0 || i > validIndex.length - 1) {
			return -1;
		} else {
			return validIndex[i];
		}
	}

	public void setSymbolList(SymbolList symbolList) {
		this.symbolList = symbolList;

		/**
		 * 索引处以前(包括自身)的gap数量
		 */
		int[] rValidIndex = new int[symbolList.length()];
		int gapCount = 0;
		for (int i = 0; i < symbolList.length(); i++) {
			if (symbolList.symbolAt(i + 1) == Util.getGapSymbol()) {
				gapCount++;
				rValidIndex[i] = -1;
			} else {
				rValidIndex[i] = i - gapCount;
			}
		}

		int validLength = symbolList.length() - gapCount;
		validIndex = new int[validLength];
		for (int i = 0; i < symbolList.length(); i++) {
			if (rValidIndex[i] != -1) {
				validIndex[rValidIndex[i]] = i;
			}
		}
	}

	public StdGene getStdGene() {
		return stdGene;
	}

	public void setStdGene(StdGene stdGene) {
		this.stdGene = stdGene;
	}

	public Properties getProperties() {
		return properties;
	}

	public void setProperties(Properties properties) {
		this.properties = properties;
	}

}
